home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / file / managers / mc-3.2 / mc-3 / mc-3.2.1 / src / profile.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-17  |  10.5 KB  |  479 lines

  1. /*
  2.  * Initialization-File Functions.
  3.  *
  4.  * From the Wine project
  5.  
  6.    Copyright (C) 1993, 1994 Miguel de Icaza.
  7.    
  8.    This program is free software; you can redistribute it and/or modify
  9.    it under the terms of the GNU General Public License as published by
  10.    the Free Software Foundation; either version 2 of the License, or
  11.    (at your option) any later version.
  12.    
  13.    This program is distributed in the hope that it will be useful,
  14.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.    GNU General Public License for more details.
  17.  
  18.    You should have received a copy of the GNU General Public License
  19.    along with this program; if not, write to the Free Software
  20.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 
  21.  */
  22.  
  23. /* "$Id: profile.c,v 1.10 1995/02/21 19:07:06 miguel Exp $" */
  24.  
  25. #include <config.h>
  26. #include <stdio.h>
  27. #include <string.h>
  28. #include <stdlib.h>    /* For free() and atoi() */
  29. #include <sys/types.h>
  30. #include "mad.h"
  31. #include "util.h"
  32. #include "global.h"
  33. #include "profile.h"
  34.  
  35. #define INIFILE "win.ini"
  36. #define STRSIZE 4096
  37. #define overflow (next == &CharBuffer [STRSIZE-1])
  38.  
  39. enum { FirstBrace, OnSecHeader, IgnoreToEOL, KeyDef, KeyDefOnKey, KeyValue };
  40.  
  41. typedef struct TKeys {
  42.     char *KeyName;
  43.     char *Value;
  44.     struct TKeys *link;
  45. } TKeys;
  46.  
  47. typedef struct TSecHeader {
  48.     char *AppName;
  49.     TKeys *Keys;
  50.     struct TSecHeader *link;
  51. } TSecHeader;
  52.     
  53. typedef struct TProfile {
  54.     char *FileName;
  55.     TSecHeader *Section;
  56.     struct TProfile *link;
  57. } TProfile;
  58.  
  59. TProfile *Current = 0;
  60. TProfile *Base = 0;
  61.  
  62. static int is_loaded (char *FileName, TSecHeader **section)
  63. {
  64.     TProfile *p = Base;
  65.  
  66.     while (p){
  67.     if (!strcasecmp (FileName, p->FileName)){
  68.         Current = p;
  69.         *section = p->Section;
  70.         return 1;
  71.     }
  72.     p = p->link;
  73.     }
  74.     return 0;
  75. }
  76.  
  77. static TSecHeader *load (char *file)
  78. {
  79.     FILE *f;
  80.     int state;
  81.     TSecHeader *SecHeader = 0;
  82.     char CharBuffer [STRSIZE];
  83.     char *next = "";        /* Not needed */
  84.     int c;
  85.     
  86.     if ((f = fopen (file, "r"))==NULL)
  87.     return NULL;
  88.  
  89.     state = FirstBrace;
  90.     while ((c = getc (f)) != EOF){
  91.     if (c == '\r')        /* Ignore Carriage Return */
  92.         continue;
  93.     
  94.     switch (state){
  95.  
  96.     case OnSecHeader:
  97.         if (c == ']' || overflow){
  98.         *next = '\0';
  99.         next = CharBuffer;
  100.         SecHeader->AppName = strdup (CharBuffer);
  101.         state = IgnoreToEOL;
  102.         } else
  103.         *next++ = c;
  104.         break;
  105.  
  106.     case IgnoreToEOL:
  107.         if (c == '\n'){
  108.         state = KeyDef;
  109.         next = CharBuffer;
  110.         }
  111.         break;
  112.  
  113.     case FirstBrace:
  114.     case KeyDef:
  115.     case KeyDefOnKey:
  116.         if (c == '['){
  117.         TSecHeader *temp;
  118.         
  119.         temp = SecHeader;
  120.         SecHeader = (TSecHeader *) xmalloc (sizeof (TSecHeader),
  121.                             "KeyDef");
  122.         SecHeader->link = temp;
  123.         SecHeader->Keys = 0;
  124.         state = OnSecHeader;
  125.         next = CharBuffer;
  126.         break;
  127.         }
  128.         if (state == FirstBrace) /* On first pass, don't allow dangling keys */
  129.         break;
  130.         
  131.         if ((c == ' ' && state != KeyDefOnKey) || c == '\t')
  132.         break;
  133.         
  134.         if (c == '\n' || overflow) /* Abort Definition */
  135.         next = CharBuffer;
  136.         
  137.         if (c == '=' || overflow){
  138.         TKeys *temp;
  139.  
  140.         temp = SecHeader->Keys;
  141.         *next = '\0';
  142.         SecHeader->Keys = (TKeys *) xmalloc (sizeof (TKeys), "KD2");
  143.         SecHeader->Keys->link = temp;
  144.         SecHeader->Keys->KeyName = strdup (CharBuffer);
  145.         state = KeyValue;
  146.         next = CharBuffer;
  147.         } else {
  148.         *next++ = c;
  149.         state = KeyDefOnKey;
  150.         }
  151.         break;
  152.  
  153.     case KeyValue:
  154.         if (overflow || c == '\n'){
  155.         *next = '\0';
  156.         SecHeader->Keys->Value = strdup (CharBuffer);
  157.         state = c == '\n' ? KeyDef : IgnoreToEOL;
  158.         next = CharBuffer;
  159. #ifdef DEBUG
  160.         printf ("[%s] (%s)=%s\n", SecHeader->AppName,
  161.             SecHeader->Keys->KeyName, SecHeader->Keys->Value);
  162. #endif
  163.         } else
  164.         *next++ = c;
  165.         break;
  166.         
  167.     } /* switch */
  168.     
  169.     } /* while ((c = getc (f)) != EOF) */
  170.     return SecHeader;
  171. }
  172.  
  173. static void new_key (TSecHeader *section, char *KeyName, char *Value)
  174. {
  175.     TKeys *key;
  176.     
  177.     key = (TKeys *) xmalloc (sizeof (TKeys), "new_key");
  178.     key->KeyName = strdup (KeyName);
  179.     key->Value   = strdup (Value);
  180.     key->link = section->Keys;
  181.     section->Keys = key;
  182. }
  183.  
  184. char *GetSetProfileChar (int set, char *AppName, char *KeyName,
  185.              char *Default, char *FileName)
  186. {
  187.     
  188.     TProfile   *New;
  189.     TSecHeader *section;
  190.     TKeys      *key;
  191.  
  192.     if (!is_loaded (FileName, §ion)){
  193.     New = (TProfile *) xmalloc (sizeof (TProfile), "GetSetProfile");
  194.     New->link = Base;
  195.     New->FileName = strdup (FileName);
  196.     New->Section = load (FileName);
  197.     Base = New;
  198.     section = New->Section;
  199.     Current = New;
  200.     }
  201.     
  202.     /* Start search */
  203.     for (; section; section = section->link){
  204.     if (section->AppName == 0 || strcasecmp (section->AppName, AppName))
  205.         continue;
  206.     for (key = section->Keys; key; key = key->link){
  207.         if (strcasecmp (key->KeyName, KeyName))
  208.         continue;
  209.         if (set){
  210.         free (key->Value);
  211.         key->Value = strdup (Default);
  212.         }
  213.         return key->Value;
  214.     }
  215.     /* If getting the information, then don't write the information
  216.        to the INI file, need to run a couple of tests with windog */
  217.     /* No key found */
  218.     if (set){
  219.         new_key (section, KeyName, Default);
  220.         return 0;
  221.     }
  222.     }
  223.     
  224.     /* Non existent section */
  225.     if (set && Default){
  226.     section = (TSecHeader *) xmalloc (sizeof (TSecHeader), "GSP3");
  227.     section->AppName = strdup (AppName);
  228.     section->Keys = 0;
  229.     new_key (section, KeyName, Default);
  230.     section->link = Current->Section;
  231.     Current->Section = section;
  232.     } 
  233.     return Default;
  234. }
  235.  
  236. short GetSetProfile (int set, char * AppName, char * KeyName, char * Default,
  237.              char * ReturnedString, short Size, char * FileName)
  238.  
  239. {
  240.     char  *s;
  241.     
  242.     s = GetSetProfileChar (set, AppName, KeyName, Default, FileName);
  243.     if (!set){
  244.     ReturnedString [Size-1] = 0;
  245.     strncpy (ReturnedString, s, Size-1);
  246.    }
  247.     return 1;
  248. }
  249.  
  250. short GetPrivateProfileString (char * AppName, char * KeyName,
  251.                    char * Default, char * ReturnedString,
  252.                    short Size, char * FileName)
  253. {
  254.     return (GetSetProfile (0, AppName, KeyName, Default, ReturnedString, Size, FileName));
  255. }
  256.  
  257. char *get_profile_string (char *AppName, char *KeyName, char *Default,
  258.               char *FileName)
  259. {
  260.     return GetSetProfileChar (0, AppName, KeyName, Default, FileName);
  261. }
  262.  
  263. int GetProfileString (char * AppName, char * KeyName, char * Default, 
  264.               char * ReturnedString, int Size)
  265. {
  266.     return GetPrivateProfileString (AppName, KeyName, Default,
  267.                     ReturnedString, Size, INIFILE);
  268. }
  269.  
  270. int GetPrivateProfileInt (char * AppName, char * KeyName, int Default,
  271.                char * File)
  272. {
  273.     static char IntBuf [15];
  274.     static char buf [15];
  275.  
  276.     sprintf (buf, "%d", Default);
  277.     
  278.     /* Check the exact semantic with the SDK */
  279.     GetPrivateProfileString (AppName, KeyName, buf, IntBuf, 15, File);
  280.     if (!strcasecmp (IntBuf, "true"))
  281.     return 1;
  282.     if (!strcasecmp (IntBuf, "yes"))
  283.     return 1;
  284.     return atoi (IntBuf);
  285. }
  286.  
  287. int GetProfileInt (char * AppName, char * KeyName, int Default)
  288. {
  289.     return GetPrivateProfileInt (AppName, KeyName, Default, INIFILE);
  290. }
  291.  
  292. int WritePrivateProfileString (char * AppName, char * KeyName, char * String,
  293.                 char * FileName)
  294. {
  295.     return GetSetProfile (1, AppName, KeyName, String, "", 0, FileName);
  296. }
  297.  
  298. int WriteProfileString (char * AppName, char * KeyName, char * String)
  299. {
  300.     return (WritePrivateProfileString (AppName, KeyName, String, INIFILE));
  301. }
  302.  
  303. static void dump_keys (FILE *profile, TKeys *p)
  304. {
  305.     if (!p)
  306.     return;
  307.     dump_keys (profile, p->link);
  308.     fprintf (profile, "%s=%s\n", p->KeyName, p->Value);
  309. }
  310.  
  311. static void dump_sections (FILE *profile, TSecHeader *p)
  312. {
  313.     if (!p)
  314.     return;
  315.     dump_sections (profile, p->link);
  316.     if (p->AppName [0]){
  317.     fprintf (profile, "\n[%s]\n", p->AppName);
  318.     dump_keys (profile, p->Keys);
  319.     }
  320. }
  321.  
  322. static void dump_profile (TProfile *p)
  323. {
  324.     FILE *profile;
  325.     
  326.     if (!p)
  327.     return;
  328.     dump_profile (p->link);
  329.     if ((profile = fopen (p->FileName, "w")) != NULL){
  330.     dump_sections (profile, p->Section);
  331.     fclose (profile);
  332.     }
  333. }
  334.  
  335. /*
  336.  * Must be called at the end of wine run
  337. */
  338.  
  339. void sync_profiles (void)
  340. {
  341.     dump_profile (Base);
  342. }
  343.  
  344. static void free_keys (TKeys *p)
  345. {
  346.     if (!p)
  347.     return;
  348.     free_keys (p->link);
  349.     free (p->KeyName);
  350.     free (p->Value);
  351.     free (p);
  352. }
  353.  
  354. static void free_sections (TSecHeader *p)
  355. {
  356.     if (!p)
  357.     return;
  358.     free_sections (p->link);
  359.     free_keys (p->Keys);
  360.     free (p->AppName);
  361.     p->link = 0;
  362.     p->Keys = 0;
  363.     free (p);
  364. }
  365.  
  366. static void free_profile (TProfile *p)
  367. {
  368.     if (!p)
  369.     return;
  370.     free_profile (p->link);
  371.     free_sections (p->Section);
  372.     free (p->FileName);
  373.     free (p);
  374. }
  375.  
  376. void free_profile_name (char *s)
  377. {
  378.     TProfile *p;
  379.     
  380.     if (!s)
  381.     return;
  382.     
  383.     for (p = Base; p; p = p->link){
  384.     if (strcmp (s, p->FileName) == 0){
  385.         free_sections (p->Section);
  386.         p->Section = 0;
  387.         p->FileName [0] = 0;
  388.         return;
  389.     }
  390.     }
  391. }
  392.  
  393. void free_profiles (void)
  394. {
  395.     free_profile (Base);
  396. }
  397.  
  398. void *profile_init_iterator (char *appname, char *file)
  399. {
  400.     TProfile   *New;
  401.     TSecHeader *section;
  402.     
  403.     if (!is_loaded (file, §ion)){
  404.     New = (TProfile *) xmalloc (sizeof (TProfile), "GetSetProfile");
  405.     New->link = Base;
  406.     New->FileName = strdup (file);
  407.     New->Section = load (file);
  408.     Base = New;
  409.     section = New->Section;
  410.     Current = New;
  411.     }
  412.     for (; section; section = section->link){
  413.     if (strcasecmp (section->AppName, appname))
  414.         continue;
  415.     return section->Keys;
  416.     }
  417.     return 0;
  418. }
  419.  
  420. void *profile_iterator_next (void *s, char **key, char **value)
  421. {
  422.     TKeys *keys = (TKeys *) s;
  423.  
  424.     if (keys){
  425.     *key   = keys->KeyName;
  426.     *value = keys->Value;
  427.     keys   = keys->link;
  428.     }
  429.     return keys;
  430. }
  431.  
  432. void profile_clean_section (char *appname, char *file)
  433. {
  434.     TSecHeader *section;
  435.  
  436.     /* We assume the user has called one of the other initialization funcs */
  437.     if (!is_loaded (file, §ion)){
  438.     fprintf (stderr,"Warning: profile_clean_section called before init\n");
  439.     return;
  440.     }
  441.     /* We only disable the section, so it will still be freed, but it */
  442.     /* won't be find by further walks of the structure */
  443.  
  444.     for (; section; section = section->link){
  445.     if (strcasecmp (section->AppName, appname))
  446.         continue;
  447.     section->AppName [0] = 0;
  448.     }
  449. }
  450.  
  451. int profile_has_section (char *section_name, char *profile)
  452. {
  453.     TSecHeader *section;
  454.  
  455.     /* We assume the user has called one of the other initialization funcs */
  456.     if (!is_loaded (profile, §ion)){
  457.     return 0;
  458.     }
  459.     for (; section; section = section->link){
  460.     if (strcasecmp (section->AppName, section_name))
  461.         continue;
  462.     return 1;
  463.     }
  464.     return 0;
  465. }
  466.  
  467. void profile_forget_profile (char *file)
  468. {
  469.     TProfile *p = Base;
  470.  
  471.     for (p = Base; Base; Base = Base->link){
  472.     if (strcasecmp (file, p->FileName))
  473.         continue;
  474.     p->FileName [0] = 0;
  475.     }
  476. }
  477.  
  478.  
  479.